DRFda serializerlar yordamida joylashtirilgan ob'ektlarni seriyalashtirish bo'yicha to'liq qo'llanma: aloqa turlari va ilg'or usullar.
Python DRF Serializer Aloqalari: Joylashtirilgan Ob'ekt Seriyalashtirishini O'zlashtirish
Django REST Framework (DRF) veb-API'larni yaratish uchun kuchli va moslashuvchan tizimni taqdim etadi. API ishlab chiqishning muhim jihati ma'lumotlar modellari orasidagi aloqalarni boshqarishdir va DRF serializerlari joylashtirilgan ob'ektlarni seriyalashtirish va deseryalashtirish uchun ishonchli mexanizmlarni taklif etadi. Ushbu qo'llanma DRF serializerlarida aloqalarni boshqarishning turli usullarini o'rganadi, amaliy misollar va eng yaxshi amaliyotlarni taqdim etadi.
Serializer Aloqalarini Tushunish
Relyatsion ma'lumotlar bazalarida aloqalar turli jadvallar yoki modellar qanday bog'langanligini belgilaydi. DRF serializerlari ma'lumotlar bazasi ob'ektlarini API iste'moli uchun JSON yoki boshqa ma'lumotlar formatlariga aylantirganda ushbu aloqalarni aks ettirishi kerak. Biz aloqalarning uchta asosiy turini ko'rib chiqamiz:
- ForeignKey (Birga-ko'p): Bir ob'ekt bir nechta boshqa ob'ektlarga bog'langan. Masalan, bir muallif ko'p kitob yozishi mumkin.
- ManyToManyField (Ko'pga-ko'p): Bir nechta ob'ekt bir nechta boshqa ob'ektlarga bog'langan. Masalan, bir nechta muallif bir nechta kitobda hamkorlik qilishi mumkin.
- OneToOneField (Birga-bir): Bir ob'ekt boshqa bir ob'ektga noyob tarzda bog'langan. Masalan, foydalanuvchi profili ko'pincha foydalanuvchi akkaunti bilan birga-bir bog'langan bo'ladi.
ForeignKey bilan Asosiy Joylashtirilgan Seriyalashtirish
Keling, ForeignKey aloqasini seriyalashtirishning oddiy misolidan boshlaylik. Quyidagi modellarni ko'rib chiqing:
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
country = models.CharField(max_length=50, default='USA') # Xalqaro kontekst uchun country maydoni qo'shildi
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books')
publication_date = models.DateField()
def __str__(self):
return self.title
Book
modelini uning tegishli Author
ma'lumotlari bilan seriyalashtirish uchun biz joylashtirilgan serializerdan foydalanishimiz mumkin:
from rest_framework import serializers
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = ['id', 'name', 'country']
class BookSerializer(serializers.ModelSerializer):
author = AuthorSerializer(read_only=True) # PrimaryKeyRelatedFielddan o'zgartirildi
class Meta:
model = Book
fields = ['id', 'title', 'author', 'publication_date']
Ushbu misolda, BookSerializer
tarkibida AuthorSerializer
maydoni mavjud. read_only=True
author
maydonini faqat o'qish uchun qiladi, bu muallifni kitob endpointi orqali o'zgartirishni oldini oladi. Agar siz muallif ma'lumotlari bilan kitoblarni yaratishingiz yoki yangilashingiz kerak bo'lsa, yozish amallarini boshqacha tarzda bajarishingiz kerak bo'ladi (quyida ko'ring).
Endi, Book
ob'ektini seriyalashtirsangiz, JSON chiqishi kitob ma'lumotlari ichida joylashtirilgan to'liq muallif tafsilotlarini o'z ichiga oladi:
{
"id": 1,
"title": "The Hitchhiker's Guide to the Galaxy",
"author": {
"id": 1,
"name": "Douglas Adams",
"country": "UK"
},
"publication_date": "1979-10-12"
}
ManyToManyField Aloqalarini Seriyalashtirish
Keling, ManyToManyField
aloqasini ko'rib chiqaylik. Faraz qilaylik, bizda Category
modeli bor va kitob bir nechta kategoriyalarga tegishli bo'lishi mumkin.
class Category(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books')
categories = models.ManyToManyField(Category, related_name='books')
publication_date = models.DateField()
def __str__(self):
return self.title
Kategoriyalarni serializers.StringRelatedField
yoki serializers.PrimaryKeyRelatedField
yordamida seriyalashtirishimiz yoki joylashtirilgan serializer yaratishimiz mumkin.
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ['id', 'name']
class BookSerializer(serializers.ModelSerializer):
author = AuthorSerializer(read_only=True)
categories = CategorySerializer(many=True, read_only=True) # ManyToManyField uchun many=True juda muhim
class Meta:
model = Book
fields = ['id', 'title', 'author', 'categories', 'publication_date']
many=True
argumenti ManyToManyField
ni seriyalashtirishda juda muhimdir. Bu serializerga kategoriya ob'ektlari ro'yxatini kutishni buyuradi. Chiqish quyidagicha ko'rinadi:
{
"id": 1,
"title": "Pride and Prejudice",
"author": {
"id": 2,
"name": "Jane Austen",
"country": "UK"
},
"categories": [
{
"id": 1,
"name": "Classic Literature"
},
{
"id": 2,
"name": "Romance"
}
],
"publication_date": "1813-01-28"
}
OneToOneField Aloqalarini Seriyalashtirish
OneToOneField
aloqalari uchun yondashuv ForeignKey ga o'xshaydi, ammo tegishli ob'ekt mavjud bo'lmasligi mumkin bo'lgan holatlarni ko'rib chiqish muhimdir.
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
bio = models.TextField(blank=True)
location = models.CharField(max_length=100, blank=True, default='Global') # Xalqaro kontekst uchun joylashuv qo'shildi
def __str__(self):
return self.user.username
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ['id', 'bio', 'location']
class UserSerializer(serializers.ModelSerializer):
profile = UserProfileSerializer(read_only=True)
class Meta:
model = User
fields = ['id', 'username', 'email', 'profile']
Chiqish quyidagicha bo'ladi:
{
"id": 1,
"username": "johndoe",
"email": "john.doe@example.com",
"profile": {
"id": 1,
"bio": "Software Engineer.",
"location": "London, UK"
}
}
Yozish Amallarini Boshqarish (Yaratish va Yangilash)
Yuqoridagi misollar asosan faqat o'qish uchun seriyalashtirishga qaratilgan. Tegishli ob'ektlarni yaratish yoki yangilashga ruxsat berish uchun siz serializerdagi create()
va update()
metodlarini bekor qilishingiz kerak.
Joylashtirilgan Ob'ektlarni Yaratish
Aytaylik, siz bir vaqtning o'zida yangi kitob va muallif yaratmoqchisiz.
class BookSerializer(serializers.ModelSerializer):
author = AuthorSerializer()
class Meta:
model = Book
fields = ['id', 'title', 'author', 'publication_date']
def create(self, validated_data):
author_data = validated_data.pop('author')
author = Author.objects.create(**author_data)
book = Book.objects.create(author=author, **validated_data)
return book
create()
metodida biz muallif ma'lumotlarini ajratib olamiz, yangi Author
ob'ektini yaratamiz va keyin yangi yaratilgan muallif bilan bog'lab Book
ob'ektini yaratamiz.
Muhim: Siz author_data
dagi mumkin bo'lgan validatsiya xatolarini boshqarishingiz kerak bo'ladi. Agar muallif ma'lumotlari noto'g'ri bo'lsa, try-except blokidan foydalanib serializers.ValidationError
ni ko'tarishingiz mumkin.
Joylashtirilgan Ob'ektlarni Yangilash
Xuddi shunday, kitobni ham, uning muallifini ham yangilash uchun:
class BookSerializer(serializers.ModelSerializer):
author = AuthorSerializer()
class Meta:
model = Book
fields = ['id', 'title', 'author', 'publication_date']
def update(self, instance, validated_data):
author_data = validated_data.pop('author', None)
if author_data:
author = instance.author
for attr, value in author_data.items():
setattr(author, attr, value)
author.save()
for attr, value in validated_data.items():
setattr(instance, attr, value)
instance.save()
return instance
update()
metodida biz mavjud muallifni olib, taqdim etilgan ma'lumotlar asosida uning atributlarini yangilaymiz va keyin kitobning atributlarini yangilaymiz. Agar author_data
taqdim etilmagan bo'lsa (ya'ni muallif yangilanmayapti), kod muallifni yangilash qismini o'tkazib yuboradi. validated_data.pop('author', None)
dagi None
standarti muallif ma'lumotlari yangilash so'roviga kiritilmagan holatlarni boshqarish uchun juda muhimdir.
PrimaryKeyRelatedField
dan Foydalanish
Joylashtirilgan serializerlar o'rniga, bog'liq ob'ektning asosiy kalitidan foydalanib aloqalarni ifodalash uchun PrimaryKeyRelatedField
dan foydalanishingiz mumkin. Bu faqat bog'liq ob'ektning ID'siga murojaat qilish kerak bo'lganda va butun ob'ektni seriyalashtirishni xohlamaganingizda foydalidir.
class BookSerializer(serializers.ModelSerializer):
author = serializers.PrimaryKeyRelatedField(queryset=Author.objects.all())
class Meta:
model = Book
fields = ['id', 'title', 'author', 'publication_date']
Endi, author
maydoni muallifning ID'sini o'z ichiga oladi:
{
"id": 1,
"title": "1984",
"author": 3, // Muallif ID'si
"publication_date": "1949-06-08"
}
Yaratish va yangilash uchun, so'rov ma'lumotlarida muallifning ID'sini uzatasiz. queryset=Author.objects.all()
taqdim etilgan ID ma'lumotlar bazasida mavjudligini ta'minlaydi.
HyperlinkedRelatedField
dan Foydalanish
HyperlinkedRelatedField
aloqalarni bog'liq ob'ektning API endpointiga giperhavolalar yordamida ifodalaydi. Bu gipermedia API'larda (HATEOAS) keng tarqalgan.
class BookSerializer(serializers.ModelSerializer):
author = serializers.HyperlinkedRelatedField(view_name='author-detail', read_only=True)
class Meta:
model = Book
fields = ['id', 'title', 'author', 'publication_date']
view_name
argumenti bog'liq ob'ekt uchun so'rovlarni boshqaradigan view nomini belgilaydi (masalan, author-detail
). Bu viewni urls.py
faylingizda belgilashingiz kerak bo'ladi.
Chiqishda muallifning batafsil endpointiga ishora qiluvchi URL mavjud bo'ladi:
{
"id": 1,
"title": "Brave New World",
"author": "http://example.com/api/authors/4/",
"publication_date": "1932-01-01"
}
Ilg'or Usullar va E'tiborga Molik Jihatlar
depth
Opsiyasi:ModelSerializer
da sizdepth
opsiyasidan foydalanib, ForeignKey aloqalari uchun ma'lum bir chuqurlikka qadar joylashtirilgan serializerlarni avtomatik yaratishingiz mumkin. Biroq, agar aloqalar murakkab bo'lsa,depth
dan foydalanish ishlash muammolariga olib kelishi mumkin, shuning uchun serializerlarni aniq belgilash tavsiya etiladi.SerializerMethodField
: Tegishli ma'lumotlar uchun maxsus seriyalashtirish mantiqini yaratish uchunSerializerMethodField
dan foydalaning. Bu ma'lumotlarni o'ziga xos tarzda formatlash yoki hisoblangan qiymatlarni kiritish kerak bo'lganda foydalidir. Masalan, muallifning to'liq ismini mahalliy tilga qarab turli tartibda ko'rsatishingiz mumkin. Ko'pgina Osiyo madaniyatlarida familiya ismdan oldin keladi.- Tasvirlashni Sozlash: Bog'liq ma'lumotlar qanday tasvirlanishini sozlash uchun serializerdagi
to_representation()
metodini bekor qiling. - Ishlashni Optimallashtirish: Murakkab aloqalar va katta ma'lumotlar to'plamlari uchun ma'lumotlar bazasi so'rovlarini optimallashtirish va ma'lumotlar bazasiga kirishlar sonini kamaytirish uchun
select_related
vaprefetch_related
kabi usullardan foydalaning. Bu, ayniqsa, sekinroq ulanishlarga ega bo'lishi mumkin bo'lgan global foydalanuvchilarga xizmat ko'rsatadigan API'lar uchun muhimdir. - Null Qiymatlarni Boshqarish: Serializerlaringizda null qiymatlar qanday boshqarilishiga e'tibor bering, ayniqsa ixtiyoriy aloqalar bilan ishlaganda. Zarur bo'lsa, serializer maydonlaringizda
allow_null=True
dan foydalaning. - Validatsiya: Ma'lumotlar yaxlitligini ta'minlash uchun kuchli validatsiyani amalga oshiring, ayniqsa bog'liq ob'ektlarni yaratish yoki yangilashda. Biznes qoidalarini majburlash uchun maxsus validatorlardan foydalanishni ko'rib chiqing. Masalan, kitobning nashr etilgan sanasi kelajakda bo'lmasligi kerak.
- Xalqaroizatsiyalash va Lokalizatsiyalash (i18n/l10n): Ma'lumotlaringiz turli tillar va mintaqalarda qanday ko'rsatilishini ko'rib chiqing. Foydalanuvchi mahalliy tiliga mos ravishda sanalar, raqamlar va valyatalarni formatlang. Xalqaroizatsiyalanuvchi satrlarni modellaringiz va serializerlaringizda saqlang.
Serializer Aloqalari Uchun Eng Yaxshi Amaliyotlar
- Serializerlarni Fokusda Saqlang: Har bir serializer o'ziga xos modelni yoki yaqin bog'liq ma'lumotlar to'plamini seriyalashtirish uchun javobgar bo'lishi kerak. Haddan tashqari murakkab serializerlarni yaratishdan saqlaning.
- Aniq Serializerlardan Foydalaning:
depth
opsiyasiga juda ko'p tayanmang. Seriyalashtirish jarayonini ko'proq nazorat qilish uchun har bir bog'liq model uchun aniq serializerlarni belgilang. - Sinfga Kirib Tekshiring: Serializerlaringiz ma'lumotlarni to'g'ri seriyalashtirayotganini va deseryalashtirayotganini, ayniqsa murakkab aloqalar bilan ishlaganda, tekshirish uchun unit testlar yozing.
- API'ingizni Hujjatlang: API endpointlaringizni va ular kutayotgan hamda qaytarayotgan ma'lumotlar formatlarini aniq hujjatlang. Interaktiv API hujjatlarini yaratish uchun Swagger yoki OpenAPI kabi vositalardan foydalaning.
- API Versiyalashni Ko'rib Chiqing: API'ingiz rivojlanar ekan, mavjud mijozlar bilan moslikni saqlash uchun versiyalashdan foydalaning. Bu eski ilovalarga ta'sir qilmasdan buzuvchi o'zgarishlarni kiritish imkonini beradi.
- Ishlashni Kuzatib Boring: API'ingizning ishlashini kuzatib boring va serializer aloqalariga oid har qanday tiqilinchlarni aniqlang. Ma'lumotlar bazasi so'rovlarini va seriyalashtirish mantiqini optimallashtirish uchun profillash vositalaridan foydalaning.
Xulosa
Django REST Framework'da serializer aloqalarini o'zlashtirish kuchli va samarali veb-API'lar yaratish uchun juda muhimdir. Aloqa turlarini va DRF serializerlarida mavjud bo'lgan turli opsiyalarni tushunish orqali siz joylashtirilgan ob'ektlarni samarali seriyalashtirishingiz va deseryalashtirishingiz, yozish amallarini boshqarishingiz va API'ingizni ishlashini optimallashtirishingiz mumkin. API'ingizni loyihalashda xalqaroizatsiyalash va lokalizatsiyalashni hisobga olishni unutmang, bu global auditoriya uchun foydalanish mumkinligini ta'minlaydi. Chuqur sinovdan o'tkazish va aniq hujjatlashtirish API'ingizning uzoq muddatli saqlanishi va foydalanishga yaroqliligini ta'minlash uchun kalit hisoblanadi.